package com.lee.ssm.controller;

import com.lee.ssm.domain.SysLog;
import com.lee.ssm.service.ISysLogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;
@Component
@Aspect
public class LogAop {

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private ISysLogService iSysLogService;
    //创建切面类处理日志
    private Date visitTime;
    private Method method;
    private Class clazz;

    @Before("execution(* com.lee.ssm.controller.*.*(..))&&!execution(* com.lee.ssm.controller.SysLog*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime=new Date();
        clazz=jp.getTarget().getClass();
        String methedName=jp.getSignature().getName();
        //获取方法参数
        Object[] args = jp.getArgs();
        //反射获取方法method(name,class[])
        if (args==null||args.length==0){
            method=clazz.getMethod(methedName);
        }else {
            Class[] classes=new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                //获取参数的class，保存在class数组中，方便反射
                classes[i]=args[i].getClass();
            }
            //有参数组
            method=clazz.getMethod(methedName,classes);
        }
    }
   @After("execution(* com.lee.ssm.controller.*.*(..))&&!execution(* com.lee.ssm.controller.SysLog*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception {
        //获取执行时间
        Long executionTime =new Date().getTime()-visitTime.getTime();
        //获取当前用户名 通过securityContext获取上下文
        SecurityContext context = SecurityContextHolder.getContext();
        //获取的是spring security框架封装的 userdetails对象
        User user = (User) context.getAuthentication().getPrincipal();
        String username=user.getUsername();


        //获取ip 根据httpRequest获取，可以web.xml配置listenter RequestContextListener 获取将HTTPRequest 注入spring中
        String remoteAddr = request.getRemoteAddr();


        //获取url 根据Annotation获取RequestMapping
        //class上的mapping 排除SysLogController的url
        String url="";
        if (clazz!=SysLogController.class){
            RequestMapping classRequestMapping = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            if (classRequestMapping!=null){
                RequestMapping methodRequestMapping = method.getAnnotation(RequestMapping.class);
                if (methodRequestMapping!=null){
                    url=classRequestMapping.value()[0]+methodRequestMapping.value()[0];
                }
            }
        }
        //封装Syslog
        SysLog sysLog=new SysLog();
        sysLog.setExecutionTime(executionTime);
        sysLog.setIp(remoteAddr);
        sysLog.setMethod("[类名]"+clazz.getName()+"[方法名]"+method.getName());
        sysLog.setUrl(url);
        sysLog.setVisitTime(visitTime);
        sysLog.setUsername(username);
        iSysLogService.save(sysLog);
    }

}
